// Copyright 2014 Google Inc. All rights reserved.
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.archivepatcher.patcher;

import com.google.archivepatcher.util.IOUtils;

import java.io.DataInput;
import java.io.IOException;

/**
 * Encapsulates functionality for reading and writing headers for patches
 * generated by this library. The header format is as follows:
 * <br>The 6-byte ASCII string "ARCPAT".
 * <br>A two-byte ASCII string containing the base-10 digits of the version
 *     number of the patch format; the maximum supported value is 99.
 */
//TODO: This should just be another Part. The custom logic here is silly.
public class PatchMagic {
    /**
     * The 6-byte ASCII string expected to be found in all patches generated by
     * this library.
     */
    private final static String MAGIC = "ARCPAT";

    /**
     * The current version of the patch format generated by and supported by
     * this library.
     */
    private final static int VERSION = 1;

    /**
     * The two-byte base-10 ASCII representation of {@link #VERSION}.
     */
    private final static String VERSION_STRING = "01";

    /**
     * A regex that matches the format specified by this class.
     */
    private final static String MAGIC_REGEX = "ARCPAT[0-9][0-9]";

    /**
     * Returns the 8-byte standard header (including version number) as String.
     * @return the header, which is always exactly 8 bytes long when output
     * as an ASCII string
     */
    public static String getStandardHeader() {
        return MAGIC + VERSION_STRING;
    }

    /**
     * Tries to read the standard header from an input stream.
     * @param in the stream to read from
     * @return the header string
     * @throws PatchParseException if unable to read the header
     */
    public static String readStandardHeader(DataInput in) throws PatchParseException {
        String header;
        try {
            header = IOUtils.readUTF8(in, getStandardHeader().length());
        } catch (IOException e) {
            throw new PatchParseException("Unable to read header", e);
        }
        if (!header.matches(MAGIC_REGEX)) throw new PatchParseException(
                "Bad header: " + header);
        return header;
    }

    /**
     * Returns the current version of the patch format generated by and
     * supported by this library. Patches whose version number is less than or
     * equal to this value are guaranteed to be supported; patches whose version
     * number is greater than this value <em>may</em> not be supported.
     * @return the current version, in the range [1, 99].
     */
    public static int getVersion() {
        return VERSION;
    }

    /**
     * Given a header string previously obtained with
     * {@link #readStandardHeader(DataInput)}, extracts the version number from
     * that header and returns it as an integer in the range [1, 99]
     * @param header
     * @return the version
     */
    public static int getVersion(String header) {
        if (!header.matches(MAGIC_REGEX)) throw new IllegalArgumentException(
                "Bad header: " + header);
        final int result = Integer.parseInt(header.substring(MAGIC.length()));
        if (result == 0) throw new IllegalArgumentException("Version is 0");
        return result;
    }
}
